home *** CD-ROM | disk | FTP | other *** search
/ The PC-SIG Library 10 / The PC-Sig Library - Shareware for the IBM PC and Compatibles (PC-SIG)(Tenth Edition Disks 1-2804)(1991).iso / PC_SIGCD / 05 / 6 / DISK0564.ZIP / SOURCE.ARC / LS.ASM < prev    next >
Assembly Source File  |  1989-04-02  |  40KB  |  1,125 lines

  1.         TITLE LS - SORTED DIRECTORY PROGRAM
  2.         PAGE  55,132
  3. ;************************************************************************
  4. ;       THIS PROGRAM DISPLAYS A SORTED DIRECTORY WITH FILE SIZES.
  5. ;       IT REQUIRES MSDOS VERSION 2 OR HIGHER.
  6. ;
  7. ;       usage:  LS [-A -D -L -N -R -S - T -1] afn
  8. ;               -A includes hidden and system files
  9. ;        -D displays information on directory (not its contents)
  10. ;               -L shows date, time, file size in bytes for each file
  11. ;        -N suppresses sorting
  12. ;        -R reverses order of sort
  13. ;        -T sorts by date/time of file
  14. ;        -S shows file sizes
  15. ;        -1 forces single-column display with no paging
  16. ;               afn may contain * and ?: e.g. "LS PROG?.*"
  17. ;
  18. ;       BY: JON DART
  19. ;           3012 HAWTHORN ST.,
  20. ;           SAN DIEGO, CA 92104
  21. ;
  22. ;    Version 3.2, 30-Mar-89 -T option without -R sorts dates so that most
  23. ;                   recent files are first (like unix).  Illegal
  24. ;                   switch error msg. also corrected.
  25. ;    Version 3.1, 21-Mar-89 fixed bug in free space display.
  26. ;    Version 3.0, 18-Jan-89 modifications to handle disks > 65 Megabytes.
  27. ;                    also a bug fix in FIXPATH.
  28. ;    Version 2.2, 30-Apr-88 allows multiple file arguments, uses GETARGS
  29. ;             library routine, adds NODUPES procedure.
  30. ;    Version 2.1, 09-Feb-88 minor cleanup, some redundant code removed.
  31. ;    Version 2.0, 28-Nov-87 fixes bug in display of very large directories.
  32. ;             -S and -D options and PAD asssembly option added.  Old
  33. ;             -D option changed to -T.
  34. ;    Version 1.9, 01-Nov-87 assembles under MASM 5.0
  35. ;    Version 1.8, 24-Oct-86 adds LOWCASE assembly option, -1, -D, -N and
  36. ;             -R switches.  Some problems in redirecting output to
  37. ;             disk were fixed.  Also minor bugs in display routine.
  38. ;    Version 1.7, 04-Oct-86 linked with new library, no longer writes
  39. ;             nulls to console (which interfered with screen print)
  40. ;    Version 1.6, 05-Jul-86 fixes sometime loss of top display line.
  41. ;             Now accepts - as well as / for switches.
  42. ;             Also modified to assemble under MASM 4.0.
  43. ;       Version 1.5, 04-May-86 fixes clear screen routine
  44. ;       Version 1.4, 17-Jan-86 UTIL and CONSOLE made external modules,
  45. ;                    adds FIXPATH function
  46. ;       Version 1,3, 07-Nov-85 /L option added
  47. ;       Version 1.2, 03-Nov-85 fixes bug in size function
  48. ;       Version 1.1, 18-Oct-85
  49. ;
  50. ;   TO BUILD LS.EXE:
  51. ;    MASM LS,LS,NUL,NUL
  52. ;    LINK LS,LS,NUL,ASM
  53. ;    EXEPACK LS.EXE LS.NEW
  54. ;    DEL LS.EXE
  55. ;    REN LS.NEW LS.EXE
  56.  
  57. TRUE    EQU     1
  58. FALSE   EQU     0
  59. IBM     EQU     TRUE            ;TRUE IF IBM-COMPATIBLE AT BIOS LEVEL
  60. LOWCASE EQU    FALSE        ;TRUE FOR LOWER-CASE OUTPUT (FOR UNIX PURISTS)
  61. PAD    EQU    TRUE        ;PAD FILE NAMES WITH SPACES (SO EXTENSIONS LINE
  62.                 ;UP). FALSE MEANS DON'T PAD WITHIN FILE NAMES.
  63. BIOS    EQU     10H             ;BIOS INTERRUPT FOR VIDEO FUNCTIONS
  64. MAXARGS EQU    100        ;MAX # COMMAND-LINE ARGUMENTS
  65. MAXFILES EQU    512             ;MAX # OF FILES
  66. NCOLUMN EQU     5               ;# OF COLUMNS TO DISPLAY (SHORT MODE,
  67.                 ;WITH NO FILE SIZES)
  68. NCOLUMNS EQU    4        ;# OF COLUMNS TO DISPLAY (SHORT MODE,
  69.                 ;WITH FILE SIZES)
  70. MAXLINES EQU    24              ;# LINES ON SCREEN FOR FILE DISPLAY
  71.     IF    IBM
  72. FENCE    EQU    179        ;VERTICAL BAR CHAR. (IBM ONLY)
  73.     ELSE
  74. FENCE   EQU     '|'             ;BORDER BETWEEN COLUMNS
  75.     ENDIF
  76. K       EQU     1024            ;1 K
  77.  
  78. M       EQU     BYTE PTR 0[BX]
  79.  
  80.         .XLIST
  81.         INCLUDE ASCII.DEF
  82.         INCLUDE MSDOS2.DEF
  83.     INCLUDE MACROS.DEF
  84.         .LIST
  85.  
  86. ERROR   MACRO   ERRNUM                  ;SHOW ERROR MESSAGE
  87.         MOV     DX,OFFSET MSG&ERRNUM
  88.     CALL    ERRORMSG
  89.     ENDM
  90.  
  91. ;    UNINITIALIZED DATA
  92.  
  93. DATA    SEGMENT PUBLIC PARA 'DATA'
  94. DGROUP  GROUP DATA
  95.     ASSUME DS:DGROUP
  96. ARGPTRS DW      MAXARGS DUP (?)         ;POINTERS TO START OF ARGUMENTS
  97. ARGBUF  DB      256 DUP (?)        ;BUFFER FOR ARGUMENTS
  98. FILNAM  DB      80 DUP (?)              ;FILE NAME FROM COMMAND LINE
  99. SPATH   DB      80 DUP (?)              ;SEARCH PATH
  100. SPREFIX DB      80 DUP (?)              ;SEARCH PREFIX (NOT USED)
  101. OUR_DTA DB      128 DUP (?)             ;DISK TRANSFER ADDRESS, USED BY MSDOS
  102.                                         ;FUNCTIONS 4EH AND 4FH.
  103. ADDRLIST DB     (2*MAXFILES) DUP (?)    ;HOLDS POINTERS TO INFO ON EACH FILE
  104. BUFFER  DB      (22*MAXFILES) DUP (?)   ;HOLDS INFO ON EACH FILE, RETURNED BY
  105.                                         ;MSDOS FUNCTION 4EH OR 4FH.
  106. ENDBUF  EQU     BUFFER+(MAXFILES*22)
  107.  
  108. STACK   SEGMENT PARA STACK 'STACK'
  109.         ASSUME SS:STACK
  110.         DB 512 DUP (?)
  111. STACK   ENDS
  112.  
  113. ;*********************
  114. ; MEMORY DEFINITIONS *
  115. ;*********************
  116. ;
  117.  
  118. SWLIST        DB    'ADLNRST1',0    ;LIST OF LEGAL SWITCHES
  119. AFLAG       DW      0               ;SET <>0 IF -A
  120. DFLAG        DW    0        ;SET <>0 IF -D
  121. LFLAG       DW      0               ;SET <>0 IF -L
  122. NFLAG        DW    0        ;SET <>0 IF -N
  123. RFLAG        DW    0        ;SET <>0 IF -R
  124. SFLAG       DW    0        ;SET <>0 IF -S
  125. TFLAG        DW    0        ;SET <>0 IF -T
  126. ONEFLAG     DW    0        ;SET <>0 IF -1
  127. DRIVE       DB      0               ;DRIVE (0 FOR DEFAULT, 1 FOR A, ETC)
  128. ISDEV        DB    0        ;=0 IF OUTPUT REDIRECTED TO DISK
  129. VPAGE       DB      0               ;VIDEO PAGE # (IBM ONLY)
  130. SCRSIZE     DB      80              ;SCREEN WIDTH (80 IS DEFAULT FOR NON-IBM)
  131. VMODE       DB      0               ;DISPLAY MODE (IBM ONLY)
  132. ATTRIBUTES     DB      00010001B       ;DEFAULT FILE ATTRIBUTES
  133. NUMFILES     DW      0               ;NUMBER OF FILES FOUND
  134. NDUPES        DW    0            ;NUMBER OF DUPLICATE FILE NAMES
  135. GAP         DW      0               ;USED BY SORT ROUTINE
  136. COLCOUNT     DW      1               ;COUNT OF COLUMNS DISPLAYED
  137. LINECOUNT     DW      1               ;COUNT OF LINES DISPLAYED
  138. FIRSTSCREEN     DW     1 DUP (?)    ;SET =1 IF -L OR -S AND FIRST SCREEN
  139. FILECOUNT     DW      0                  ;COUNT OF FILES DISPLAYED
  140. BASE        DW      1            ;FIRST FILE TO SHOW
  141. NEXTFREE     DW      1 DUP (?)       ;ADDR. OF NEXT FREE SLOT IN BUFFER
  142. MAXLINE     DW      1 DUP (?)       ;NO. OF LINES TO DISPLAY
  143. MAXFILE     DW      1 DUP (?)       ;MAX FILE TO SHOW
  144. MAXCOL      DB      1 DUP (?)       ;COLUMN WIDTH OF DISPLAY
  145. FILESPERSCREEN  DW 1 DUP (?)        ;FILES PER SCREEN
  146. LOSIZE  DW      1 DUP (?)               ;USED IN CALCULATING FREE SPACE
  147. USED    DQ      0                       ;COUNT OF FILE SPACE USED
  148. DEFAULT DB      '????????.???',0        ;DEFAULT FILE NAME
  149. TXT0    DB      '<DIR','>',0            ;SAY IT'S A DIR
  150. TXT1    DB      ' files, using ',0
  151. TXT2    DB      ' bytes ','(',0
  152. TXT3    DB      ' bytes free',')',0
  153. TXT4    DB      ' free',')',0
  154. TXT5    DB    CR,LF,0
  155. MSG2    DB      ' : no matching files.',CR,LF,0
  156. MSG3    DB      '[ More ] ',0
  157. MSG4    DB    CR,LF,'illegal switch: ',0
  158. MSG5    DB      CR,LF,'too many arguments',CR,LF,0
  159.  
  160. DATA    ENDS
  161.  
  162. CODE    SEGMENT PUBLIC PARA 'CODE'
  163.     ASSUME CS:CODE
  164.         EXTRN   SKIPSP:NEAR,UC:NEAR,DECOUT:NEAR,CPYCNT:NEAR,CPY:NEAR
  165.     EXTRN   UCSTR:NEAR
  166.     EXTRN    CMDSRC:NEAR
  167.         EXTRN   ERRORMSG:NEAR
  168.     EXTRN    TYPTX:NEAR
  169.     EXTRN    PRTSTR:NEAR
  170.         EXTRN   PRINTDD:NEAR
  171.         EXTRN   COUT:NEAR,CIN:NEAR,CLRCO:NEAR,CRLF:NEAR
  172.         EXTRN   FIXPATH:NEAR
  173.     EXTRN   TYPE_DIR:ABS
  174.     EXTRN   GETARGS:NEAR
  175.  
  176. ;*********************
  177. ; START OF CODE HERE *
  178. ;*********************
  179. ENTRY:
  180.         TEST_DOS2                       ;TEST FOR DOS 2.0, EXIT IF DOS 1
  181.     PUSH    DS
  182.     MOV    AX,DGROUP
  183.     MOV    DS,AX
  184.     MOV    AL,0            ;PREPARE TO CHECK DEVICE STATUS
  185.     MOV    BX,1            ;OF STDOUT
  186.     MOV    AH,IO_CTL
  187.     INT    DOS            ;GET STATUS
  188.     AND    DX,0080H        ;MASK ISDEV BIT
  189.     MOV    BYTE PTR ISDEV,DL    ;SAVE RESULT
  190.         IF      IBM
  191.         MOV     AH,15
  192.         INT     BIOS                    ;GET VIDEO MODE
  193.         MOV     BYTE PTR VPAGE,BH       ;STORE VIDEO PAGE #
  194.         MOV     BYTE PTR SCRSIZE,AH     ;STORE CHARS/LINE
  195.         MOV     BYTE PTR VMODE,AL       ;STORE DISPLAY MODE
  196.         ENDIF
  197.     POP    DS
  198.         CALL    PARSE_SWITCHES        ;PARSE COMMAND-LINE SWITCHES
  199.         MOV     AX,OFFSET BUFFER
  200.         MOV     WORD PTR NEXTFREE,AX    ;INIT "NEXTFREE" TO START OF FILE LIST
  201. GETFILES:
  202.     PUSH    CX
  203.     PUSH    SI
  204.     CALL    PARSE_ARG        ;BUILD SEARCH PATH
  205.         CALL    FIND_FILES              ;SEARCH FOR FILES, BUILD LIST IN MEMORY
  206.     POP    SI
  207.     POP    CX
  208.     ADD    SI,2
  209.     CMP    CX,0
  210.     JLE    SORT
  211.     LOOP    GETFILES
  212. SORT:
  213.         CALL    SORT_FILES              ;SORT FILE LIST
  214.         CALL    SHOW_INFO               ;SHOW DISK USAGE INFO
  215.         CALL    SHOW_FILES              ;DISPLAY DIRECTORY
  216.         MOV     AX,256*EXIT
  217.         INT     DOS                     ;EXIT TO DOS
  218.  
  219. ;***********************************************
  220. ; PARSE COMMAND LINE SWITCHES                  *
  221. ; ENTRY:   DS:BX POINTS TO DOS COMMAND LINE    *
  222. ; RETURNS: CX = # OF ARGUMENTS (LESS SWITCHES) *
  223. ;       SI = POINTER TO ARGUMENT POINTERS   *
  224. ;***********************************************
  225. PARSE_SWITCHES  PROC  NEAR
  226.     MOV    AX,DGROUP
  227.     MOV    ES,AX
  228.         MOV     BX,(80H)             ;GET BYTE COUNT FOR COMMAND LINE
  229.         PUSH    BX
  230.         MOV     DL,[BX]
  231.         MOV     DH,0
  232.         ADD     BX,DX
  233.         INC     BX
  234.         MOV     [BX],BYTE PTR 0         ;PUT 0 BYTE AT END OF COMMAND LINE
  235.         POP     BX
  236.         INC     BX
  237.     MOV    SI,OFFSET ARGPTRS
  238.     MOV    DI,OFFSET ARGBUF
  239.     MOV    CX,MAXARGS
  240.     CALL    GETARGS            ;COLLECT COMMAND LINE ARGUMENTS
  241.     JNB    L_2            ;IF OK
  242. TOOMANY:
  243.         ERROR   5                       ;TOO MANY ARGUMENTS (PRETTY UNLIKELY)
  244.     MOV    AL,5            ;SET EXIT CODE
  245.     MOV    AH,EXIT
  246.     INT    DOS            ;EXIT TO DOS
  247. ;***************************
  248. ; COLLECT SWITCHES, IF ANY *
  249. ;***************************
  250. L_2:
  251.     MOV    AX,DGROUP
  252.     MOV    DS,AX            ;POINT TO OUR DATA SEG, NOT PSP
  253.     MOV    SI,OFFSET ARGPTRS
  254. NEXTSW:
  255.     MOV    BX,WORD PTR [SI]    ;POINT TO ARGUMENT
  256.     MOV    AL,BYTE PTR [BX]    ;GET 1ST CHAR.
  257.         CMP     AL,'-'
  258.         JE      GOTSW                   ;IF SWITCH SPECIFIED
  259.     CMP    AL,'/'
  260.     JE     GOTSW
  261.     RET
  262. GOTSW:
  263.         INC     BX                      ;SKIP OVER SWITCH CHARACTER
  264.     MOV    AL,BYTE PTR [BX]
  265. SWLOOP:
  266.         CALL    UC                      ;MAKE SWITCH UPPER CASE
  267.     PUSH    BX
  268.     MOV    BX,OFFSET SWLIST
  269.     CALL    CMDSRC            ;SEARCH LIST OF VALID SWITCHES
  270.     POP    BX
  271.     MOV    AH,0
  272.     ADD    AX,AX            ;NOT FOUND IN LIST?
  273.     JZ    BADSWITCH        ;NO.
  274.     MOV    DI,OFFSET AFLAG - 2
  275.     ADD    DI,AX            ;POINT TO FLAG
  276.     NOT    WORD PTR [DI]        ;1'S COMPLEMENT
  277.     INC    BX
  278.     MOV    AL,BYTE PTR [BX]    ;GET NEXT CHAR. FROM LINE
  279.     COMPLIST <SPACE,TAB,NULL>,ENDSW ;IF DELIM
  280.     JMP    SWLOOP            ;ELSE ASSUME THIS IS A SWITCH CHAR.
  281. ENDSW:    ADD    SI,2            ;POINT TO NEXT POINTER TO AN ARG
  282.     LOOP    NEXTSW
  283.     RET                ;NO ARGS BESIDES SWITCHES
  284. BADSWITCH:
  285.         ERROR   4                       ;ILLEGAL SWITCH
  286.     MOV    AL,BYTE PTR [BX]
  287.         CALL    COUT                    ;DISPLAY BAD CHAR.
  288.     CALL    CRLF
  289.     MOV    AL,4            ;SET EXIT CODE
  290.     MOV    AH,EXIT
  291.     INT    DOS            ;EXIT TO DOS
  292. PARSE_SWITCHES  ENDP
  293.  
  294. ;*****************************************************************
  295. ; TAKE A COMMAND LINE ARGUMENT AND SET UP SEARCH PATH IN "SPATH" *
  296. ;*****************************************************************
  297. PARSE_ARG PROC    NEAR
  298.     CMP    CX,0
  299.     JE    NONAME            ;IF NULL ARGUMENT
  300.     MOV    BX,[SI]
  301.     MOV    AL,BYTE PTR [BX+1]
  302.         CMP     AL,':'            ;SEE IF DRIVE SPECIFIED
  303.         JNE     NODRIVE                 ;IF NOT
  304.         MOV     AL,BYTE PTR [BX]        ;GET DRIVE LETTER
  305.         CALL    UC                      ;MAKE UPPER-CASE
  306.         MOV     BYTE PTR FILNAM,AL       ;SAVE DRIVE LETTER IN FILE NAME BUFFER
  307.         MOV     BYTE PTR (FILNAM+1),':'   ;SAVE COLON ALSO
  308.         SUB     AL,'A'-1                ;CONVERT ASCII TO BINARY (A=1, ETC.)
  309.         MOV     BYTE PTR DRIVE,AL       ;SAVE BINARY DRIVE
  310.         ADD     BX,2                    ;SKIP OVER DRIVE AND COLON
  311.         CALL    SKIPSP                  ;ANYTHING AFTER DRIVE SPEC?
  312.         MOV     SI,BX                   ;SAVE START OF FILE NAME, JUST IN CASE
  313.         JNB     DRVPLUSFILE             ;IF FILE NAME GIVEN, COPY INTO NAME BUFFER
  314.         MOV     SI,OFFSET DEFAULT       ;ELSE SI POINTS TO DEFAULT FILE NAME
  315. DRVPLUSFILE:
  316.         MOV     DI,OFFSET FILNAM+2      ;DI POINTS TO DESTINATION
  317.         JMP     SHORT COPYNAME2         ;GO COPY FILENAME TO FILE BUFFER
  318. NONAME: 
  319.         MOV     SI,OFFSET DEFAULT    ;IF NO NAME, JUST COPY DEFAULT TO FILNAM
  320.         MOV     DI,OFFSET FILNAM
  321.         JMP     SHORT COPYNAME2
  322. NODRIVE:
  323. COPYNAME:
  324.         MOV     SI,BX                   ;DS:SI POINTS TO START OF NAME
  325.         MOV     DI,OFFSET FILNAM
  326. COPYNAME2:
  327.         MOV     CX,80
  328.         CALL    CPYCNT                  ;SAVE FILE NAME
  329.         MOV     BX,OFFSET FILNAM        ;BX - FILE NAME
  330.         MOV     CX,OFFSET SPATH         ;CX - STORAGE FOR SEARCH PATH
  331.         MOV     DX,OFFSET SPREFIX       ;DX - STORAGE FOR SEARCH PREFIX (NOT USED)
  332.         CALL    FIXPATH                 ;PARSE FILE NAME
  333.     CMP    AX,TYPE_DIR
  334.     JE    GOTDIR            ;IF DIRECTORY
  335.         RET
  336. GOTDIR:    CMP    BYTE PTR DFLAG,0    ;-D FLAG SET?
  337.     JNE    DFLAGSET
  338.     RET
  339. DFLAGSET:
  340.     MOV    SI,OFFSET FILNAM
  341.     MOV    DI,OFFSET SPATH
  342.     MOV    CX,65
  343.     CALL    CPYCNT            ;MAKE SEARCH PATH = FILE NAME
  344.     RET    
  345. PARSE_ARG ENDP
  346.  
  347. ;**********************
  348. ; FILE SEARCH ROUTINE *
  349. ;**********************
  350. FIND_FILES PROC NEAR
  351.         MOV     DX,OFFSET OUR_DTA       ;LOAD DTA OFFSET
  352.         MOV     AH,SET_DTA
  353.  
  354.         INT     DOS                     ;SET UP DTA
  355.         MOV     CX,WORD PTR ATTRIBUTES  ;GET DEFAULT ATTRIBUTES
  356.         CMP     BYTE PTR AFLAG,0        ;A FLAG SET?
  357.         JE      SHORT NOAFLAG           ;NO
  358.         OR      CX,00000110B            ;YES, SET SYSTEM & HIDDEN ATTRIBUTES
  359. NOAFLAG:
  360. ;***********************
  361. ; SEARCH FOR 1ST MATCH *
  362. ;***********************
  363.         MOV     DX,OFFSET SPATH         ;POINT TO SEARCH PATH
  364.         MOV     AH,FIND_FIRST
  365.         INT     DOS                     ;SEARCH FOR 1ST MATCH
  366.         JNC     FOUND1ST                ;IF FOUND
  367.     MOV    DX,OFFSET TXT5
  368.     CALL    ERRORMSG
  369.     MOV    DX,OFFSET FILNAM    ;POINT TO FILE NAME
  370.     CALL    ERRORMSG
  371.     ERROR    2            ;NO MATCHING FILES
  372.     MOV    AX,256*EXIT+2
  373.     INT    DOS
  374. ;*********************************************************************
  375. ; COLLECT FILE INFO BLOCKS IN BUFFER, POINTERS TO BLOCKS IN ADDRLIST *
  376. ;*********************************************************************
  377. FOUND1ST:
  378. FOUND1: INC     WORD PTR NUMFILES
  379.         CMP     WORD PTR NUMFILES,MAXFILES
  380.         JGE     LASTFILE
  381.         MOV     DI,WORD PTR NEXTFREE
  382.         PUSH    DI
  383.         MOV     SI,OFFSET OUR_DTA+21
  384.         MOV     CX,22
  385.         CALL    CPY             ;COPY FILE INFO TO TABLE
  386.         MOV     AX,WORD PTR OUR_DTA+26  ;LSW OF FILE SIZE
  387.         MOV     DX,WORD PTR OUR_DTA+28  ;MSW OF FILE SIZE
  388.         ADD     AX,WORD PTR USED        ;ADD LSW OF FILE SIZE TO
  389.                                         ;LSW OF USED COUNT
  390.         MOV     WORD PTR USED,AX
  391.         ADC     WORD PTR USED+2,DX      ;NOW ADD MSW
  392.         ADD     WORD PTR NEXTFREE,22
  393.         MOV     AX,NUMFILES
  394.         ADD     AX,AX
  395.         ADD     AX,OFFSET ADDRLIST
  396.         MOV     SI,AX
  397.         POP     BX
  398.         MOV     WORD PTR [SI],BX   ;STORE ADDR IN LIST
  399.         MOV     AH,FIND_NEXT
  400.         INT     DOS             ;FIND NEXT FILE
  401.         JNC     FOUND1          ;LOOP UNTIL NO MORE
  402. LASTFILE:
  403.         RET
  404. FIND_FILES ENDP
  405.  
  406. ;********************************************************
  407. ; SORT POINTERS IN ADDRLIST, USING SHELL SORT ALGORITHM *
  408. ;********************************************************
  409. SORT_FILES PROC NEAR
  410.     CMP    BYTE PTR NFLAG,0    ;CHECK N FLAG
  411.     JNE    NODUPES            ;IF NO SORTING
  412.         MOV     AX,WORD PTR NUMFILES
  413. SORT1:                    ;TOP OF LOOP 1
  414.         SHR     AX,1
  415.         MOV     WORD PTR GAP,AX
  416.         JNZ     SORT11            ;DONE IF GAP = 0
  417.  
  418. ;***********************************************************
  419. ; make one more pass to eliminate duplicate file names     *
  420. ; (necessary if user types something like "LS *.ASM H*.*") *
  421. ;***********************************************************
  422. NODUPES:
  423.     MOV    AX,WORD PTR NUMFILES
  424.     CMP    AX,2
  425.     JGE    NODUPES0
  426.     RET
  427. NODUPES0:
  428.     MOV    CX,1
  429. NODUPES1:
  430.     MOV    AX,WORD PTR NDUPES
  431.     AND    AX,AX
  432.     JZ    NODUPES2
  433.     ADD    AX,CX
  434.     MOV    SI,AX
  435.     ADD    SI,SI
  436.     ADD    SI,OFFSET ADDRLIST
  437.     MOV    DI,CX
  438.     ADD    DI,DI
  439.     ADD    DI,OFFSET ADDRLIST
  440.     MOV    AX,WORD PTR [SI]
  441.     MOV    WORD PTR [DI],AX
  442. NODUPES2:
  443.     MOV    DX,CX
  444.     INC    DX
  445.     ADD    DX,WORD PTR NDUPES
  446.     CALL    COMPARE
  447.     JNE    NODUPES3
  448.     INC    WORD PTR NDUPES        ;BUMP # OF DUPLICATES
  449. NODUPES3:
  450.     INC    CX
  451.     MOV    AX,WORD PTR NUMFILES
  452.     CMP    CX,AX
  453.     JL    NODUPES1
  454.     MOV    AX,WORD PTR NUMFILES
  455.     SUB    AX,WORD PTR NDUPES
  456.     MOV    WORD PTR NUMFILES,AX
  457.         RET
  458.  
  459. SORT11:
  460.         INC     AX
  461.         MOV     BX,AX            ;BX = COUNTER FOR LOOP 2
  462. SORT2:  CMP     BX,WORD PTR NUMFILES    ;TOP OF LOOP 2
  463.         JG      SHORT SORT5
  464.         MOV     CX,BX
  465. SORT3:                    ;TOP OF LOOP 3
  466.         MOV     DX,CX
  467.         SUB     CX,WORD PTR GAP
  468.         JBE     SHORT SORT4
  469.     CMP    BYTE PTR TFLAG,0
  470.     JE    SORT3A            ;IF SORTING NAMES
  471.     CALL    COMPDATE        ;SORTING DATES, USE SPECIAL COMPARE
  472.     JMP    SHORT SORT3B
  473.     CALL    SWAP
  474.     JMP    SORT3
  475. SORT3A:
  476.         CALL    COMPARE                 ;COMPARE ADDRLIST[DX], ADDRLIST[CX]
  477. SORT3B:
  478.     MOV    AX,0
  479.         JLE     SORT3C
  480.     NOT    AX
  481. SORT3C:
  482.     CMP    BYTE PTR RFLAG,0    ;R FLAG SET?
  483.     JE    SORT3D            ;NO
  484.     NOT    AX            ;YES, NEGATE RESULT OF COMPARISON
  485. SORT3D: 
  486.     AND    AX,AX
  487.     JZ    SORT4
  488.         CALL    SWAP            ;OUT OF ORDER, SO SWAP
  489.         JMP     SORT3            ;BOTTOM OF LOOP 3
  490. SORT4:
  491.         INC     BX
  492.         JMP     SORT2            ;BOTTOM OF LOOP 2
  493. SORT5:
  494.         MOV     AX,WORD PTR GAP
  495.         JMP     SORT1            ;BOTTOM OF LOOP 1
  496. SORT_FILES ENDP
  497.  
  498. ;********************************************************
  499. ; COMPARE TWO FILE NAMES                                *
  500. ; ENTRY:  CX AND DX ARE INDEX TO POINTERS (1..NUMFILES) *
  501. ;         IN ADDRLIST                                   *
  502. ;********************************************************
  503. COMPARE PROC    NEAR
  504.         PUSH    CX
  505.         MOV     SI,CX
  506.         ADD     SI,SI
  507.         ADD     SI,OFFSET ADDRLIST
  508.         MOV     AX,WORD PTR [SI]
  509.         ADD     AX,9
  510.         MOV     SI,AX
  511.         MOV     DI,DX
  512.         ADD     DI,DI
  513.         ADD     DI,OFFSET ADDRLIST
  514.         MOV     AX,WORD PTR [DI]
  515.         ADD     AX,9
  516.         MOV     DI,AX
  517.         MOV     CX,11
  518.     COMP_STRINGS
  519.         POP     CX
  520.         RET
  521. COMPARE ENDP
  522.  
  523. ;*********************************************************
  524. ; COMPARE TWO FILES BY DATE                              *
  525. ; ENTRY:   CX AND DX ARE INDEX TO POINTERS (1..NUMFILES) *
  526. ;         IN ADDRLIST                                   *
  527. ;*********************************************************
  528. COMPDATE PROC    NEAR
  529.         PUSH    CX
  530.         MOV     SI,CX
  531.         ADD     SI,SI
  532.         ADD     SI,OFFSET ADDRLIST
  533.         MOV     AX,WORD PTR [SI]
  534.         MOV     SI,AX
  535.         MOV     DI,DX
  536.         ADD     DI,DI
  537.         ADD     DI,OFFSET ADDRLIST
  538.         MOV     AX,WORD PTR [DI]
  539.         MOV     DI,AX
  540.     MOV    AX,WORD PTR [DI+3]
  541.     CMP    AX,WORD PTR [SI+3]
  542.     JNE    COMPD1            ;J/IF DATES NOT =
  543.     MOV    AX,WORD PTR [DI+1]    ;COMPARE TIMES
  544.     CMP    AX,WORD PTR [SI+1]
  545. COMPD1:
  546.         POP     CX
  547.         RET
  548. COMPDATE ENDP
  549.  
  550. ;*********************************************************
  551. ; SWAP TWO OUT-OF-ORDER FILES                            *
  552. ; ENTRY:   CX AND DX ARE INDEX TO POINTERS (1..NUMFILES) *
  553. ;        IN ADDRLIST                                   *
  554. ;*********************************************************
  555. SWAP    PROC    NEAR
  556.         PUSH    BX
  557.         MOV     SI,CX
  558.         ADD     SI,SI
  559.         ADD     SI,OFFSET ADDRLIST
  560.         MOV     BX,WORD PTR [SI]
  561.         MOV     DI,DX
  562.         ADD     DI,DI
  563.         ADD     DI,OFFSET ADDRLIST
  564.         MOV     AX,WORD PTR [DI]
  565.         MOV     WORD PTR [SI],AX
  566.         MOV     WORD PTR [DI],BX
  567.         POP     BX
  568.         RET
  569. SWAP    ENDP
  570.  
  571. ;********************
  572. ; DISPLAY DIRECTORY *
  573. ;********************
  574. SHOW_FILES PROC NEAR
  575.         MOV     SI,OFFSET ADDRLIST
  576.     MOV    WORD PTR FIRSTSCREEN,0
  577.     MOV    AL,BYTE PTR LFLAG
  578.     OR    AL,BYTE PTR SFLAG    ;S OR L FLAG SET?
  579.     JZ    DISP0A            ;NO
  580.     INC    WORD PTR FIRSTSCREEN    ;YES, SET FLAG
  581. DISP0A:
  582.     CMP    BYTE PTR ONEFLAG,0
  583.     JE    DISP0            ;IF -1 FLAG NOT SET
  584.         MOV     AX,WORD PTR NUMFILES    ;NUMBER OF FILES THERE ARE
  585.         MOV     WORD PTR MAXFILE,AX     ;=LAST FILE # TO DISPLAY
  586.     MOV    BX,2            ;INDEX TO 1ST FILE
  587.     JMP    DISP11            ;GO SHOW FILES IN 1 COLUMN
  588. DISP0:
  589.         MOV     BYTE PTR MAXCOL,2    ;INITIALIZE MAXCOL FOR LONG DISPLAY
  590.         CMP     BYTE PTR LFLAG,0        ;LONG DISPLAY FLAG SET?
  591.         JNE     DISP2                   ;YES, KEEP MAXCOL INTACT
  592.     CMP    BYTE PTR SFLAG,0    ;S FLAG SET?
  593.     JE    DISP1            ;NO
  594.         MOV     BYTE PTR MAXCOL,NCOLUMNS   ;YES, SET MAXCOL APPROPRIATELY
  595.     JMP    SHORT DISP2
  596. DISP1:    MOV    BYTE PTR MAXCOL,NCOLUMN    ;SET NCOLUMN FOR SHORT DISPLAY, NO SIZES
  597. DISP2:
  598.         MOV     BL,BYTE PTR MAXCOL
  599.         MOV     AL,MAXLINES
  600.     SUB    AL,BYTE PTR FIRSTSCREEN
  601.         MUL     BL                      ;COMPUTE (MAXLINES)*MAXCOL
  602.     MOV    WORD PTR FILESPERSCREEN,AX ; SAVE RESULT
  603.         ADD     AX,WORD PTR BASE        ;ADD BASE TO GET LAST FILE # WE
  604.                                         ;CAN SHOW ON THIS SCREEN
  605.         MOV     BX,AX
  606.         MOV     AX,WORD PTR NUMFILES    ;COMPARE WITH TOTAL # FILES
  607.         INC     AX                      ;+1
  608.         CMP     AX,BX                   ;WILL ALL FILES FIT ON SCREEN?
  609.         JG      DISP6                   ;NO
  610.     MOV    AX,WORD PTR NUMFILES    ;GET MAX. FILE NUMBER
  611.     SUB    AX,WORD PTR BASE    ;FIND HOW MANY FILES TO GO
  612.     INC    AX
  613.         DIV     BYTE PTR MAXCOL         ;COMPUTE # OF LINES/COLUMN
  614.         CMP     AH,0                    ;IS REMAINDER 0?
  615.         JE      DISP5                   ;YES, SKIP AHEAD
  616.         INC     AL                      ;NO, ADD 1 TO LINE COUNT
  617. DISP5:  MOV     AH,0                    ;ZERO HI BYTE OF LINES/COLUMN
  618.         MOV     WORD PTR MAXLINE,AX     ;MAXLINE=# OF LINES TO SHOW IN
  619.                                         ;THIS SCREEN
  620.         MOV     AX,WORD PTR NUMFILES    ;NUMBER OF FILES THERE ARE
  621.         MOV     WORD PTR MAXFILE,AX     ;=LAST FILE # TO DISPLAY
  622.         JMP     SHORT DISP7
  623. DISP6:  MOV     AX,MAXLINES             ;TOO MANY FILES FOR 1 SCREEN, SO
  624.     SUB    AX,WORD PTR FIRSTSCREEN
  625.         MOV     WORD PTR MAXLINE,AX     ;USE WHOLE SCREEN FOR DISPLAY
  626.     MOV    AX,WORD PTR FILESPERSCREEN ; GET MAX. FILES/SCREEN
  627.         MOV     WORD PTR MAXFILE,AX     ;STORE AS # OF FILES TO SHOW
  628. DISP7:
  629.         MOV     WORD PTR COLCOUNT,1    ;START AT COLUMN 1
  630.     MOV    WORD PTR LINECOUNT,1    ;AND LINE 1
  631.         MOV     WORD PTR FILECOUNT,0    ;# OF FILES DISPLAYED IN THIS SCREEN
  632. DISP8:
  633.         MOV     CX,1                    ;CX WILL COUNT UP TO COLCOUNT
  634.         MOV     BX,0                    ;BX WILL HOLD (CX-1)*MAXLINE
  635. DISP9:                                  ;COMPUTE (COLCOUNT-1)*MAXLINE
  636.         CMP     CX,WORD PTR COLCOUNT
  637.         JGE     DISP10
  638.         ADD     BX,WORD PTR MAXLINE
  639.         INC     CX
  640.         JMP     DISP9
  641. DISP10:
  642.         ADD     BX,WORD PTR LINECOUNT   ;ADD LINE COUNT
  643.         DEC     BX                      ;-1
  644.         ADD     BX,WORD PTR BASE        ;ADD TO BASE
  645.         CMP     BX,WORD PTR NUMFILES    ;BLANK SLOT IN LAST COLUMN?
  646.         JG      DISP12                   ;YUP.
  647.     ADD    BX,BX            ;DOUBLE BX TO GET INDEX TO ADDRLIST
  648.         CMP     WORD PTR COLCOUNT,1     ;1ST COLUMN?
  649.         JE      DISP11                   ;YES, NO FENCE
  650.         CALL    DOFENCE                 ;SHOW FENCE
  651. DISP11:
  652.         MOV     DI,WORD PTR [SI+BX]     ;GET ADDRESS OF FILE INFO
  653.     PUSH    BX
  654.         CALL    SHOW                    ;SHOW A FILE
  655.         CALL    BUMPCOL                 ;UPDATE LINE & COLUMN COUNTS
  656.     POP    BX
  657.         INC     WORD PTR FILECOUNT      ;BUMP FILE COUNT
  658.         MOV     AX,WORD PTR FILECOUNT   ;GET IT
  659.         CMP     AX,WORD PTR MAXFILE     ;DONE ALL FILES?
  660.         JGE     DISP14                  ;IF DONE
  661.     CMP    BYTE PTR ONEFLAG,0    ;TEST 1-COLUMN FLAG
  662.     JE    DISP13            ;IF NOT SET, DO PAGING
  663.     CALL    CRLF            ;SHOW CR/LF
  664.     ADD    BX,2            ;ADVANCE TO NEXT SLOT IN ADDRLIST
  665.     JMP    DISP11            ;DO NEXT FILE
  666. DISP12:
  667.         CALL    BUMPCOL
  668. DISP13:
  669.         MOV     AX,WORD PTR LINECOUNT   ;GET LINE COUNT
  670.         CMP     AX,WORD PTR MAXLINE     ;IS IT >MAX LINE?
  671.         JLE     DISP8                   ;IF NOT
  672.  
  673. ;       COME HERE WHEN SCREEN IS FULL OR ALL FILES DONE:
  674. DISP14:
  675.     CMP    BYTE PTR ONEFLAG,0
  676.     JE    DISP15            ;IF NOT -1
  677.     RET                ;DONE IF -1
  678. DISP15:
  679.         CMP     WORD PTR COLCOUNT,1     ;IS COLUMN COUNT =1?
  680.         JE      DISP16                  ;YES, NO CR NEEDED
  681.     CMP    WORD PTR NUMFILES,0    ;WAS AT LEAST ONE FILE DISPLAYED?
  682.     JE    DISP16            ;NO, NO CR NEEDED
  683.         CALL    CRLF                    ;SHOW CR AFTER LAST LINE
  684. DISP16:
  685.         MOV     AX,WORD PTR BASE
  686.         ADD     AX,WORD PTR MAXFILE
  687.         MOV     WORD PTR BASE,AX        ;GET BASE FOR NEXT SCREEN
  688.         MOV     BX,AX
  689.         MOV     AX,WORD PTR NUMFILES
  690.         SUB     AX,BX                   ;COMPUTE # FILES REMAINING
  691.         JBE     DISP17                  ;IF NO MORE
  692.         CALL    WAITCR                  ;WAIT FOR USER
  693.     MOV    WORD PTR FIRSTSCREEN,0    ;CLEAR "FIRST SCREEN" FLAG
  694.         JMP     DISP2                   ;DO NEXT SCREEN
  695. DISP17:
  696.         RET
  697. SHOW_FILES ENDP
  698.  
  699. BUMPCOL PROC    NEAR
  700.     CMP    BYTE PTR ONEFLAG,0
  701.     JNE    BC1            ;JUST RETURN IF 1 COLUMN
  702.         INC     WORD PTR COLCOUNT       ;BUMP COLUMN COUNT
  703.         MOV     AX,WORD PTR COLCOUNT
  704.         CMP     AL,BYTE PTR MAXCOL      ;PAST LAST COLUMN?
  705.         JLE     BC1                     ;NO, KEEP GOING
  706.         CALL    CRLF                    ;YES, START NEW LINE
  707.         MOV     WORD PTR COLCOUNT,1     ;RESET COLUMN COUNTER
  708.         INC     WORD PTR LINECOUNT      ;UPDATE LINE COUNTER
  709. BC1:
  710.         RET
  711. BUMPCOL ENDP
  712.  
  713. DOFENCE PROC    NEAR                    ;SHOW "FENCE" BETWEEN COLUMNS
  714.         CMP     BYTE PTR LFLAG,0        ;L FLAG SET?
  715.         JE      SHORTFENCE              ;NO.
  716.     CALL    TWOSP
  717.     MOV    AX,FENCE
  718.         CALL    COUT
  719. TWOSP:
  720.     MOV    AL,SPACE        ;YES, LONGER GAP BTWN. COLUMNS
  721.     CALL    COUT
  722.     MOV    AL,SPACE
  723.     CALL    COUT
  724.         RET
  725. SHORTFENCE:
  726.         MOV    AX,SPACE
  727.     CALL    COUT
  728.     MOV    AX,FENCE
  729.     CALL    COUT
  730.     MOV    AX,SPACE
  731.     CALL    COUT
  732.         RET
  733. DOFENCE ENDP
  734.  
  735. ;*******************************************
  736. ; SHOW FILE NAME, SIZE (DI POINTS TO INFO) *
  737. ;*******************************************
  738. SHOW    PROC    NEAR
  739.         PUSH    DI
  740.         MOV     CX,8
  741. SHOWNAME:                               ;SHOW FILE NAME
  742.         MOV     AL,BYTE PTR [DI+9]      ;GET CHAR.
  743.         CMP     AL,'.'
  744.         JE      SHOW1                   ;DOT MEANS END OF NAME
  745.         CMP     AL,0
  746.         JE      SHOW1            ;SO DOES NULL
  747.     IF    LOWCASE
  748.     CALL    LC            ;MAKE LOWER CASE
  749.     ENDIF
  750.         CALL    COUT                    ;SHOW CHAR.
  751.         INC     DI                      ;BUMP POINTER
  752.     DEC    CX
  753.     JMP    SHOWNAME        ;LOOP
  754.  
  755. SHOW1:
  756.     IF    PAD
  757.     PUSH    AX                      ;FOUND END OF NAME, UNUSED COUNT IN CX
  758.         CALL    SPOUT                   ;WRITE CX SPACES
  759.         POP     AX
  760.     ENDIF
  761.     CMP    AL,'.'            ;WAS LAST CHAR DOT?
  762.     JNE    NODOT            ;NO
  763.     INC    DI            ;POINT PAST DOT
  764.     MOV    AX,'.'
  765.         CALL    COUT                    ;NOW WRITE DOT
  766.     JMP    SHORT SHOW3
  767. NODOT:    MOV    AX,SPACE        ;SHOW SPACE (INSTEAD OF DOT)
  768.     CALL    COUT
  769. SHOW3:
  770.     PUSH    CX
  771.     MOV     CX,3                    ;PREPARE TO SHOW EXTENSION (3 CHARS.)
  772. SHOW4:  MOV     AL,BYTE PTR [DI+9]      ;GET CHAR.
  773.         CMP     AL,0
  774.         JE      SHOW4A                  ;IF NULL, SHOW A SPACE
  775.     IF    LOWCASE    
  776.     CALL    LC            ;MAKE LOWER CASE
  777.     ENDIF
  778.         INC     DI                      ;BUMP POINTER
  779.     JMP    SHORT SHOW4B
  780. SHOW4A:    MOV    AX,SPACE
  781. SHOW4B:    
  782.         CALL    COUT                    ;SHOW CHAR.
  783.         LOOP    SHOW4            ;LOOP
  784.     POP    CX
  785. SHOW5:  
  786.     CALL    SPOUT                   ;PAD OUT FIELD
  787. SHOW6:  POP     DI                      ;POINT TO START OF INFO AGAIN
  788.         MOV     AL,BYTE PTR [DI]        ;GET FILE ATTRIBUTE
  789.         AND     AL,00010000B            ;IS IT A DIRECTORY?
  790.         JZ      SHOW7                   ;NO.
  791.         CMP     BYTE PTR LFLAG,0        ;LONG DISPLAY?
  792.         JE      SHOW6B                  ;NO
  793.         MOV     CX,3                    ;YES, 3 EXTRA SPACES
  794.         CALL    SPOUT
  795. SHOW6B:                                 ;HAVE DIRECTORY
  796.     CMP    BYTE PTR SFLAG,0
  797.     JNE    SHOW6C            ;IF S FLAG SET
  798.     CMP    BYTE PTR LFLAG,0
  799.     JNE    SHOW6C            ;IF L FLAG SET
  800.     RET                ;OTHERWISE JUST RETURN
  801. SHOW6C:
  802.     MOV    DX,OFFSET TXT0
  803.     CALL    PRTSTR            ;PRINT <DIR>
  804.         CMP     BYTE PTR LFLAG,0        ;IS L FLAG SET?
  805.         JNE     SHOW8A                  ;YES, FINISH UP
  806.         RET                             ;NO, ALL DONE
  807. SHOW7:                                  ;HAVE FILE, NOT DIR
  808.         CMP     BYTE PTR LFLAG,0        ;L FLAG SET?
  809.         JNE     SHOW8                   ;YES, LONG DISPLAY
  810.     CMP    BYTE PTR SFLAG,0    ;S FLAG SET?
  811.     JE    SHOW9            ;NO, SUPPRESS FILE SIZE DISPLAY
  812.         MOV     AX,WORD PTR [DI+5]      ;SHORT DISPLAY, GET LSW FILE SIZE
  813.     MOV    DX,WORD PTR [DI+7]    ;AND MSW FILE SIZE
  814.         CALL    MAKEK                   ;CONVERT TO KBYTES
  815.         MOV     AL,SPACE                ;WITH LEADING SPACES,
  816.         MOV     CX,5                    ;AND FIELD WIDTH = 5,
  817.         CALL    DECOUT                  ;SHOW FILE SIZE
  818. SHOW9:
  819.         RET                             ;DONE
  820.  
  821. SHOW8:  MOV     AX,WORD PTR [DI+5]      ;LONG DISPLAY
  822.         PUSH    SI                      ;MOVE SIZE TO DI:SI
  823.         MOV     SI,AX
  824.         MOV     AX,WORD PTR [DI+7]
  825.         PUSH    DI
  826.         MOV     DI,AX
  827.         MOV     AL,SPACE                ;WITH LEADING SPACES,
  828.         CALL    PRINTDD                 ;SHOW FILE SIZE IN BYTES
  829.         POP     DI
  830.         POP     SI
  831. SHOW8A:
  832.         MOV     CX,2
  833.         CALL    SPOUT                   ;PRINT 2 SPACES
  834.         MOV     AX,WORD PTR [DI+3]      ;GET PACKED DATE
  835.         CALL    PRTDTE                  ;SHOW IT
  836.         MOV     CX,2
  837.         CALL    SPOUT                   ;PRINT 2 SPACES
  838.         MOV     AX,WORD PTR [DI+1]      ;GET PACKED TIME
  839.         CALL    PRTTME                  ;SHOW IT
  840.         RET                             ;DONE
  841. SHOW    ENDP
  842.  
  843.     IF     LOWCASE
  844. ;************************************
  845. ; CONVERT CHAR. IN AL TO LOWER CASE *
  846. ;************************************
  847. LC    PROC    NEAR
  848.     CMP    AL,'A'
  849.     JL    NOTUC
  850.     CMP    AL,'Z'
  851.     JG    NOTUC
  852.     ADD    AL,'a'-'A'
  853. NOTUC:
  854.     RET
  855. LC    ENDP
  856.     ENDIF
  857.  
  858. ;*******************************************
  859. ; SUBROUTINE - WRITES CX SPACES TO SCREEN  *
  860. ;*******************************************
  861. SPOUT   PROC    NEAR
  862.         JCXZ    SPOUT1
  863.         MOV     AL,SPACE
  864.         CALL    COUT
  865.         DEC     CX
  866.         JMP     SPOUT
  867. SPOUT1: RET
  868. SPOUT   ENDP
  869.  
  870. ;****************************************
  871. ; SUBROUTINE - PAUSES AT END OF SCREEN  *
  872. ;****************************************
  873. WAITCR  PROC    NEAR
  874.     CMP    BYTE PTR ISDEV,0  ;ARE WE WRITING TO A DEVICE?
  875.     JE    FILEOUT        ;NO
  876.     MOV    DX,OFFSET MSG3
  877.     CALL    ERRORMSG    ;PROMPT USER FOR OK TO SHOW NEXT SCREEN
  878.         CALL    CLRCO           ;CLEAR TYPE-AHEAD
  879.         CALL    CIN             ;GET A CHAR.
  880.         CALL    CLRSCR          ;CLEAR SCREEN
  881.         RET
  882. FILEOUT:
  883.     CALL    CRLF        ;FILE OUTPUT, JUST SHOW CR/LF TO SEPARATE SCREENS
  884.     RET
  885. WAITCR  ENDP
  886.  
  887. ;********************************************
  888. ; ROUTINE TO CLEAR SCREEN, HOME CURSOR:     *
  889. ; (MAY HAVE TO CHANGE FOR NON-IBM MACHINES) *
  890. ;********************************************
  891. CLRSCR  PROC    NEAR
  892.         PUSH    BX
  893.         IF      IBM
  894.         MOV     DX,0
  895.         CALL    MOVEXY                  ;MOVE TO HOME POSITION
  896.         MOV     AL,BYTE PTR VMODE      ;GET CURRENT VIDEO MODE
  897.         MOV     AH,0
  898.         INT     BIOS                    ;RESET MODE (CLEARS SCREEN)
  899.         ELSE
  900.         MOV     AL,FF                   ;NON-IBM CLEAR SCREEN
  901.         CALL    COUT                    ;USE FF (WILL WORK ON MOST TERMINALS)
  902.         ENDIF
  903.         POP     BX
  904.         RET
  905. CLRSCR  ENDP
  906.  
  907. ;*****************************************
  908. ; CURSOR POSITIONING ROUTINE (USES BIOS) *
  909. ;*****************************************
  910. MOVEXY  PROC    NEAR                    ;MOVE TO ROW (DH) AND COLUMN (DL)
  911.         MOV     AH,2
  912.         MOV     BH,BYTE PTR VPAGE       ;VIDEO PAGE #
  913.         MOV     BL,0                    ;COLOR (DON'T CHANGE)
  914.         INT     BIOS                    ;MOVE CURSOR
  915.         RET
  916. MOVEXY  ENDP
  917.  
  918. ;**************************************************
  919. ; DISPLAY NUMBER OF FILES, SPACE USED, SPACE FREE *
  920. ;**************************************************
  921. SHOW_INFO PROC NEAR
  922.     MOV    AL,BYTE PTR SFLAG
  923.     OR    AL,BYTE PTR LFLAG    ;S OR L FLAG SET?
  924.     JNE    INFO0A            ;YES, GO AHEAD
  925.     RET                ;NO, SUPPRESS DISPLAY
  926. INFO0A:
  927.         MOV     BX,WORD PTR NUMFILES    ;GET NUMBER OF FILES
  928.     OR    BX,BX            ;> 0?
  929.     JNE    INFO0B            ;YES, GO AHEAD
  930.     RET
  931. INFO0B:
  932.         MOV     AL,0                    ;SUPPRESS LEADING 0'S
  933.         MOV     CX,5                    ;FIELD WIDTH = 5
  934.         CALL    DECOUT                  ;SHOW # FILES
  935.     MOV    DX,OFFSET TXT1
  936.     CALL    PRTSTR
  937.         CMP     BYTE PTR LFLAG,0        ;L FLAG SET?
  938.         JE      INFO1                   ;NO, SHORT DISPLAY
  939.         MOV     DI,WORD PTR USED+2
  940.         MOV     SI,WORD PTR USED        ;GET SPACE USED IN SI:DI
  941.         MOV     AL,0                    ;SUPPRESS LEADING 0'S
  942.         CALL    PRINTDD                 ;SHOW SPACE USED
  943.     MOV    DX,OFFSET TXT2
  944.     CALL    PRTSTR
  945.         JMP     SHORT INFO2
  946. INFO1:                                  ;SHORT DISPLAY
  947.         MOV     AX,WORD PTR USED
  948.         MOV     DX,WORD PTR USED+2      ;GET AMT. USED IN DX:AX
  949.         CALL    MAKEK                   ;CONVERT TO K
  950.         MOV     AL,0                    ;SUPPRESS LEADING 0'S
  951.         MOV     CX,5                    ;FIELD WIDTH = 5
  952.         CALL    DECOUT                  ;SHOW AMT. USED
  953.     IF    LOWCASE
  954.     MOV    AL,'k'
  955.     ELSE
  956.         MOV     AL,'K'
  957.     ENDIF
  958.         CALL    COUT                    ;SHOW LETTER K
  959. INFO2:
  960.         MOV     AH,CURRENT_DISK
  961.         INT     DOS                     ;GET CURRENT DISK
  962.         PUSH    AX                      ;SAVE IT
  963.         MOV     DL,BYTE PTR DRIVE       ;DL = DRIVE WE SPECIFIED
  964.         CMP     DL,0                    ;CURRENT DISK?
  965.         JE      NOCHANGE                ;YES, NO NEED TO CHANGE
  966.         INC     AL
  967.         CMP     AL,DL                   ;SAME AS CURRENT DISK?
  968.         JE      NOCHANGE                ;YES, NO NEED TO CHANGE
  969.         DEC     DL                      ;MAKE 0=A, ETC.
  970.         MOV     AH,SELECT_DISK
  971.         INT     DOS                     ;SELECT DISK
  972. NOCHANGE:
  973.         MOV     DL,0                    ;NOW USING CURRENT DISK,
  974.         MOV     AH,GET_FREE_SPACE
  975.         INT     DOS                     ;GET FREE SPACE
  976.         MUL     BX                      ;COMPUTE # SECTORS FREE
  977.         PUSH    DX                      ;SAVE HI WORD
  978.         MUL     CX                      ;MULTIPLY LO WORD OF SECTOR COUNT
  979.                                         ;BY BYTES/SECTOR
  980.         MOV     WORD PTR LOSIZE,AX      ;SAVE LO WORD OF FREE SPACE
  981.         POP     BX                      ;GET HI WORD OF SECTOR COUNT
  982.         PUSH    DX                      ;SAVE CARRY FROM LO WORD MULT.
  983.         MOV     AX,BX                   ;MULTIPLICAND IN AX
  984.         MUL     CX                      ;MULTIPLY HI WORD OF SECTOR COUNT
  985.                                         ;TIMES BYTES/SECTOR
  986.         POP     BX                      ;GET CARRY FROM LO WORD
  987.         ADD     AX,BX                   ;ADD IT
  988.         MOV     DX,AX                   ;DX = HI WORD OF FREE SPACE
  989.         MOV     AX,WORD PTR LOSIZE      ;AX = LO WORD OF FREE SPACE
  990.         CMP     BYTE PTR LFLAG,0        ;L FLAG SET?
  991.         JE      INFO3                   ;NO, SHORT DISPLAY
  992.         MOV     DI,DX                   ;LONG DISPLAY,
  993.         MOV     SI,AX                   ;MOVE AMT. FREE TO DI:SI
  994.         MOV     AL,0                    ;SUPPRESS LEADING 0'S
  995.         CALL    PRINTDD                 ;SHOW AMT. FREE
  996.     MOV    DX,OFFSET TXT3
  997.     CALL    PRTSTR
  998.         JMP     SHORT INFO4
  999. INFO3:                                  ;SHORT DISPLAY
  1000.     CMP    DX, K
  1001.     JGE    BIG_DISK        ;IF >65 MEGABYTES
  1002.  
  1003.         MOV     CX,K                    ;CX = 1 K
  1004.         DIV     CX                      ;DIVIDE TO GET KBYTES FREE
  1005.     MOV    DX, 0
  1006.     JMP    SHORT INFO3A
  1007.  
  1008. BIG_DISK:
  1009.     MOV    CX, 10*K
  1010.     DIV    CX            ;DIVIDE BY 10K
  1011.     MOV    BX,10
  1012.     MUL    BX            ;GET KBYTES FREE IN DX:AX
  1013.  
  1014. INFO3A:
  1015.     PUSH    AX            ;SAVE LO WORD OF SPACE FREE
  1016.         MOV     AL,SPACE
  1017.         CALL    COUT                    ;WRITE SPACE
  1018.         MOV     AL,'('
  1019.         CALL    COUT                    ;WRITE PAREN
  1020.     POP    SI            ;RESTORE LO WORD OF SPACE FREE
  1021.         MOV     DI,DX                   ;LONG DISPLAY,
  1022.         MOV     AL,0                    ;SUPPRESS LEADING 0'S
  1023.         CALL    PRINTDD                 ;SHOW AMT. FREE
  1024.     IF    LOWCASE
  1025.     MOV    AL,'k'
  1026.     ELSE
  1027.     MOV    AL,'K'
  1028.     ENDIF
  1029.     CALL    COUT
  1030.     MOV    DX,OFFSET TXT4
  1031.     CALL    PRTSTR
  1032. INFO4:
  1033.         CALL    CRLF                    ;SHOW CR/LF
  1034.         POP     DX
  1035.         MOV     AH,SELECT_DISK          ;RESET DEFAULT DISK
  1036.         INT     DOS
  1037.         RET                             ;DONE
  1038. SHOW_INFO ENDP
  1039.  
  1040. ;***************************************************
  1041. ; MAKEK = TAKE QUAD # IN DX:AX, CONVERT TO K IN BX *
  1042. ;***************************************************
  1043. MAKEK   PROC    NEAR
  1044.         MOV     BX,K
  1045.         DIV     BX                      ;DIVIDE TO GET SIZE IN K
  1046.         MOV     BX,AX                   ;QUOTIENT IN BX
  1047.         CMP     DX,0                    ;MODULUS>0?
  1048.         JE      NOROUND
  1049.         INC     BX                      ;IF SO, ROUND UP
  1050. NOROUND:
  1051.         RET
  1052. MAKEK   ENDP
  1053.  
  1054. ;       The following two routines are adapted from SDIR Version
  1055. ;       2.4, by Ted Reuss (modified from a program by John Chapman), on
  1056. ;       PC-SIG Volume 185.
  1057.  
  1058.         SUBTTL  PRINT DATE, TIME & # FILES ROUTINES
  1059.         PAGE
  1060.  
  1061. ; PC-DOS packed date   <yyyyyyym mmmddddd>
  1062. P_DTE       RECORD  P_YR:7,P_MO:4,P_DY:5
  1063. ; PC-DOS packed time   <hhhhhmmm mmmsssss>
  1064. P_TME       RECORD  P_HR:5,P_MI:6,P_2S:5
  1065.  
  1066. PRTDTE  PROC    NEAR    ;Print packed date in AX as MM/DD/YY
  1067.         OR      AX,AX
  1068.         JNZ     K1              ;If date <> 0
  1069.         MOV     CX,8
  1070.         CALL    SPOUT            ;Print 8 spaces
  1071.         RET
  1072. K1:     PUSH    AX
  1073.         AND     AX,MASK P_MO    ;Mask the month,
  1074.         MOV     CL,P_MO         ; set shift count,
  1075.         SHR     AX,CL           ; right justify, &
  1076.         CALL    PRTBCD          ; print it.
  1077.         MOV     AX,'/'
  1078.         CALL    COUT
  1079.         POP     AX
  1080.         PUSH    AX
  1081.         AND     AX,MASK P_DY    ;Mask the day &
  1082.         CALL    PRTBCD          ; print it.
  1083.         MOV     AX,'/'
  1084.         CALL    COUT
  1085.         POP     AX
  1086.         AND     AX,MASK P_YR    ;Mask the year,
  1087.         MOV     CL,P_YR         ; set shift count,
  1088.         SHR     AX,CL           ; right justify,
  1089.         ADD     AX,80           ; add in year bias, &
  1090.                                 ; print it.
  1091. PRTBCD: AAM                     ;Convert AL to BCD
  1092.         OR      AX,'00'         ;Convert to ASCII
  1093.         PUSH    AX
  1094.         MOV     AL,AH
  1095.         CALL    COUT            ;High order digit
  1096.         POP     AX
  1097.         CALL    COUT            ;Low order digit
  1098.         RET
  1099. PRTDTE  ENDP
  1100.  
  1101. PRTTME  PROC    NEAR            ;Print packed time in AX as HH:MM
  1102.         OR      AX,AX
  1103.         JNZ     L1              ;if date<>0
  1104.         MOV     CX,5
  1105.         CALL    SPOUT           ;Print 5 spaces
  1106.         RET
  1107. L1:     PUSH    AX
  1108.         AND     AX,MASK P_HR    ;Mask the hours,
  1109.         MOV     CL,P_HR         ; set shift count,
  1110.         SHR     AX,CL           ; right justify, &
  1111.         CALL    PRTBCD          ; print it.
  1112.         MOV     AX,':'
  1113.         CALL    COUT
  1114.         POP     AX
  1115.         AND     AX,MASK P_MI    ;Mask the minutes,
  1116.         MOV     CL,P_MI         ; set shift count,
  1117.         SHR     AX,CL           ; right justify, &
  1118.         CALL    PRTBCD          ; print it.
  1119.         RET
  1120. PRTTME  ENDP
  1121.  
  1122. CODE    ENDS
  1123.         END     ENTRY
  1124.  
  1125.